package com.cjh.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.cjh.annotation.WebLog;
import com.cjh.pojo.Admin;
import com.cjh.pojo.Forget;
import com.cjh.pojo.User;
import com.cjh.service.AdminService;
import com.cjh.service.IMailService;
import com.cjh.service.SendSms;
import com.cjh.service.UserService;
import com.cjh.utils.Md5SaltEncode;
import com.cjh.utils.RedisUtil;
import com.cjh.vo.ResultMap;
import com.ramostear.captcha.HappyCaptcha;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@RestController
@RequestMapping("/accountApi")
public class AccountController {

    @Autowired
    private UserService userService;
    @Autowired
    private AdminService adminService;
    @Autowired
    private IMailService iMailService;
    @Autowired
    private SendSms sendSms;
    @Autowired
    private RedisUtil redisUtil;

    private final Logger logger = LoggerFactory.getLogger(AccountController.class);

    @PostMapping("/login")
    @WebLog(description = "请求=>系统登录接口")
    public ResultMap login(@RequestParam(value = "userName",required = false) String userName,
                           @RequestParam(value = "passWord",required = false) String passWord,
                           @RequestParam(value = "status",required = false) String status,
                           HttpSession session){
        if(!Objects.equals(status,"user")&&!Objects.equals(status,"admin")){
            return ResultMap.fail(405,"根据用户名、密码、身份登录","身份不合法",0);
        }

        // 获取当前用户
        Subject subject = SecurityUtils.getSubject();
        // 封装用户的登录数据
        passWord=Md5SaltEncode.md5Hash(passWord, userName,3);
        UsernamePasswordToken token = new UsernamePasswordToken(userName, passWord, status);
        System.out.println("login方法执行前===");
        try {
            // 执行登录方法，没有异常则成功
            subject.login(token);
            return ResultMap.ok(200,"根据用户名、密码、身份登录",status,1);
        } catch (UnknownAccountException e) {// 用户名不存在
            return ResultMap.fail(404,"根据用户名、密码、身份登录","用户不存在",1);
        } catch (IncorrectCredentialsException e) {// 密码错误
            return ResultMap.fail(500,"根据用户名、密码、身份登录","密码错了",0);
        }


    }

    @GetMapping("/getLoginObj/{status}")
    @WebLog(description = "请求=>获取登录用户的信息接口")
    public ResultMap getLoginObj(@PathVariable("status") String status,HttpSession session){
        switch (status){
            case "user":
                User user = (User) session.getAttribute("user");
                return ResultMap.ok(200,"获取用户账号的信息",user,1);
            default:
                Admin admin = (Admin) session.getAttribute("admin");
                return ResultMap.ok(200,"获取管理员账号的信息",admin,1);
        }

    }

    @GetMapping("/logout")
    @WebLog(description = "请求=>系统注销接口")
    public void logout(HttpSession session) throws InterruptedException {
        Thread.sleep(1500);
        User sessionUser = (User) session.getAttribute("user");
        if (!Objects.isNull(sessionUser)) redisUtil.del("user:" + sessionUser.getId());
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
    }

    @PostMapping("/getEmailCode/{status}")
    @WebLog(description = "请求=>发送QQ邮箱验证码接口")
    public ResultMap getEmailCode(@RequestParam(value = "email",required = false) String email,@PathVariable("status") String status) {

        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.eq("email",email);
        int count = userService.count(queryWrapper);
        logger.info(count>0 ? "邮箱存在，不能注册":"邮箱不存在，可以注册");
        if (count>0){

            //用户请求注册时才提示邮箱已存在，存在则不能注册
            if (Objects.equals(status,"register")){
                return ResultMap.fail(0,"QQ邮箱已存在","EXIST",count);
            }

        }else{
            //用户请求找回密码时才提示邮箱不存在，不存在则不能找回密码
            if (Objects.equals(status,"forget")){
                return ResultMap.fail(0,"发送QQ邮箱验证码","NO_EXIST",count);
            }

        }

        //6位数随机验证码
        double random = (Math.random() * 899999) + 100001;
        logger.info("验证码："+(int) random);
        boolean flag = iMailService.sendSimpleMail(email, "找回密码", "您的邮箱验证码：" + (int) random+",该验证码一分钟内有效。");
        if (!flag){
            return ResultMap.fail(500,"发送QQ邮箱验证码失败，系统异常","ERROR");
        }
        redisUtil.set("emailCode",(int) random,60);
        return ResultMap.ok(200,"发送QQ邮箱验证码","SUCCESS");
    }

    @PostMapping("/getSmsCode")
    @WebLog(description = "请求=>发送短信验证码接口")
    public ResultMap getSmsCode(@RequestParam(value = "telephone",required = false) String telephone) {

        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.eq("telephone",telephone);
        int count = userService.count(queryWrapper);
        logger.info(count>0 ? "手机号码存在，不能注册":"手机号码不存在，可以注册");
        if (count>0){
            return ResultMap.fail(0,"手机号码已存在","EXIST",count);
        }

        //6位数随机验证码
        int random = (int) ((Math.random() * 899999) + 100001);
        logger.info("验证码："+ random);
        Map<String,Object> code=new HashMap<>();
        code.put("code",random);
        //发送短信
        boolean flag = sendSms.send(telephone,"SMS_211488455",code);

        if (!flag){
            return ResultMap.fail(500,"发送短信验证码失败，系统异常","ERROR");
        }
        redisUtil.set("smsCode",(int) random,60);
        return ResultMap.ok(200,"发送短信验证码","SUCCESS");
    }

//    /**
//     * 根据QQ邮箱验证码注册
//     * @param user
//     * @param code
//     * @return
//     */
//    @PostMapping("/register")
//    @WebLog(description = "请求=>用户注册接口")
//    public ResultMap register(User user,@RequestParam(value = "code",required = false) String code) {
//        Integer emailCode = (Integer) redisUtil.get("emailCode");
//        //验证码过期
//        if (Objects.isNull(emailCode)){
//            return new ResultMap<String>(0,"邮箱验证码过期","TIMEOUT");
//        }
//        //验证码是否正确
//        if (Objects.equals(code,emailCode.toString())){
//            user.setRegisterdate(new Date());
//            user.setAvatar("/img/user_avatar.jpg");
//            //盐值加密
//            user.setPassword(Md5SaltEncode.md5Hash(user.getPassword(), user.getUsername(), 3));
//            QueryWrapper queryWrapper=new QueryWrapper();
//            queryWrapper.eq("username",user.getUsername());
//            int count = userService.count(queryWrapper);
//
//            if (count==0){
//                userService.save(user);
//                return new ResultMap<String>(200,"注册成功","SUCCESS");
//            }
//
//            return new ResultMap<String>(0,"用户名存在，注册失败","EXIST");
//        }else{
//            return new ResultMap<String>(0,"验证码错误，注册失败","ERROR");
//        }
//
//    }

    /**
     * 根据短信验证码注册
     * @param user
     * @param code
     * @return
     */
    @PostMapping("/register")
    @WebLog(description = "请求=>用户注册接口")
    public ResultMap register(User user,@RequestParam(value = "code",required = false) String code) {
        Integer smsCode = (Integer) redisUtil.get("smsCode");
        //验证码过期
        if (Objects.isNull(smsCode)){
            return ResultMap.fail(0,"短信验证码过期","TIMEOUT");
        }
        //验证码是否正确
        if (Objects.equals(code,smsCode.toString())){
            user.setRegisterDate(new Date());
            user.setAvatar("/img/user_avatar.jpg");
            //盐值加密
            user.setPassWord(Md5SaltEncode.md5Hash(user.getPassWord(), user.getUserName(), 3));
            //检查用户名是否存在
            QueryWrapper queryUserNameWrapper=new QueryWrapper();
            queryUserNameWrapper.eq("user_name",user.getUserName());
            int count = userService.count(queryUserNameWrapper);

            if (count>0){
                return ResultMap.fail(0,"用户名存在，注册失败","USER_NAME_EXIST");
            }
            //检查QQ邮箱是否存在
            QueryWrapper queryEmailWrapper=new QueryWrapper();
            queryEmailWrapper.eq("email",user.getEmail());
            int countTwo = userService.count(queryEmailWrapper);

            if (countTwo>0){
                return ResultMap.fail(0,"QQ邮箱存在，注册失败","EMAIL_EXIST");
            }

            userService.save(user);
            return ResultMap.ok(200,"注册成功","SUCCESS");

        }else{
            return ResultMap.fail(0,"验证码错误，注册失败","ERROR");
        }

    }

    @PostMapping("/forget")
    @WebLog(description = "请求=>找回密码接口")
    public ResultMap forget(Forget forget, HttpServletRequest request) {

        //校验图形验证码
        boolean flag = HappyCaptcha.verification(request,forget.getChartCode(),true);
        //图形验证码正确
        if(flag){
            logger.info("图形验证码验证通过√");

            Integer emailCode = (Integer) redisUtil.get("emailCode");
            //判断验证码是否存在
            if (emailCode==null) return ResultMap.fail(0,"邮箱验证码过期","TIMEOUT");
            //邮箱验证码正确
            if (Objects.equals(emailCode.toString(),forget.getEmailCode())){

                //全部校验成功
                return ResultMap.ok(200,"邮箱验证码正确","SUCCESS");
            }else{
                return ResultMap.fail(0,"邮箱验证码错误","EMAIL_CODE_ERROR");
            }
        }else{
            logger.info("图形验证码验证不通过×");
            return ResultMap.fail(0,"图形验证码错误","CHART_CODE_ERROR");
        }
    }

    @PutMapping("/reset")
    @WebLog(description = "请求=>重置密码接口")
    public ResultMap reset(Forget forget) {

        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.eq("user_name",forget.getUserName());
        int count = userService.count(queryWrapper);
        if(count>0){
            queryWrapper.eq("email",forget.getEmail());
            int isRight = userService.count(queryWrapper);
            if (isRight>0){
                UpdateWrapper updateWrapper=new UpdateWrapper();
                //盐值加密
                forget.setPassWord(Md5SaltEncode.md5Hash(forget.getPassWord(), forget.getUserName(),3));
                updateWrapper.set("pass_word",forget.getPassWord());
                updateWrapper.eq("user_name",forget.getUserName());
                userService.update(updateWrapper);
                return ResultMap.ok(200,"重置密码成功","SUCCESS");
            }else{
                return ResultMap.fail(0,"重置密码失败，邮箱和用户名未绑定","NO_BIND");
            }

        }
        return ResultMap.fail(0,"重置密码失败，用户名不存在","NO_EXIST");

    }

}
